{{- /* BEGIN DEFINE */ -}}

{{- define "Entity"}}
{{- $EntityName := (print .Name)}}

type {{$EntityName}} struct {
	Id int64
	syncable pb.{{.Name}}

{{- range .Fields}}
{{- if .IsComponent}}
	{{.Name}} *{{.Type}}
{{- end}}
{{- end}}
	dirty uint64
}
{{- range .Fields}}
{{- if .IsComponent}}

func (this *{{$EntityName}}) Set{{.Name}}(v *{{.Type}}) {
	if v != this.{{.Name}} {
		this.{{.Name}} = v
		this.syncable.{{.Name}} = &v.syncable
		v.dirthParent = func() {
			this.markDirty({{.Number}})
		}
		this.markDirty(uint64(0x01) << {{.Number}})
	}
}
{{- else}}

func (this *{{$EntityName}}) Set{{.Name}}(v {{.Type}}) {
	if v != this.syncable.{{.Name}} {
		this.syncable.{{.Name}} = v
		this.markDirty(uint64(0x01) << {{.Number}})
	}
}
{{- end}}
{{- end}}

func (e *{{$EntityName}}) markDirty(n uint64) {
	if e.dirty & n == n {
		return
	}
	e.dirty |= n
}

func (e *{{$EntityName}}) clearDirty() {
	if e.dirty == 0 {
		return
	}
	e.dirty = 0
}

func (e *{{$EntityName}}) MarshalMask() *pb.{{.Name}} {
	v := new(pb.{{.Name}})
{{- range .Fields}}
	if e.dirty & uint64(0x01) << {{.Number}} != 0 {
{{- if .IsComponent}}
		v.{{.Name}} = e.{{.Name}}.MarshalMask()
{{- else}}
		v.{{.Name}} = e.syncable.{{.Name}}
{{- end}}
	}
{{- end}}
	return v
}
{{- end}}

{{- define "Component"}}
{{- $ComponentName := (print .Name)}}

type {{$ComponentName}} struct {
	syncable pb.{{.Name}}

{{- range .Fields}}
	{{- if .IsComponent}}
	{{.Name}} *{{.Type}}
	{{- end}}
{{- end}}
	dirty uint64
	dirthParent dirthParentFunc
}

{{- range .Fields}}

{{- if .IsComponent}}

func (this *{{$ComponentName}}) Set{{.Name}}(v *{{.Type}}) {
	if v != this.{{.Name}} {
		this.{{.Name}} = v
		this.syncable.{{.Name}} = &v.syncable
		this.markDirty(uint64(0x01) << {{.Number}})
	}
}
{{- else}}

func (this *{{$ComponentName}}) Set{{.Name}}(v {{.Type}}) {
	if v != this.syncable.{{.Name}} {
		this.syncable.{{.Name}} = v
		this.markDirty(uint64(0x01) << {{.Number}})
	}
}
{{- end}}
{{- end}}

func (this *{{$ComponentName}}) markDirty(n uint64) {
	if this.dirty&n == n {
		return
	}
	this.dirty |= n
	this.dirthParent.invoke()
}

func (e *{{$ComponentName}}) clearDirty() {
	if e.dirty == 0 {
		return
	}
	e.dirty = 0
}

func (c *{{$ComponentName}}) MarshalMask() *pb.{{.Name}} {
	if c == nil {
		return nil
	}
	v := new(pb.{{.Name}})
{{- range .Fields}}
	if c.dirty & uint64(0x01) << {{.Number}} != 0 {
{{- if .IsComponent}}
		v.{{.Name}} = c.{{.Name}}.MarshalMask()
{{- else}}
		v.{{.Name}} = c.syncable.{{.Name}}
{{- end}}
	}
{{- end}}
	return v
}
{{- end}}

{{- /* END DEFINE */ -}}

// Code generated by kds. DO NOT EDIT.
// source: {{"TODO: Source File"}}

package {{.Package}};

import (
	"kds/example/pb"
)

type dirthParentFunc func()

func (f dirthParentFunc) invoke() {
	if f == nil {
		return
	}
	f()
}

{{- range .Entities}}
{{- template "Entity" .}}
{{- end}}

{{- range .Components}}
{{- template "Component" .}}
{{- end}}